package net.siufung.core.result;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.google.common.collect.Maps;
import lombok.Getter;
import lombok.Setter;
import net.siufung.core.result.ResultFail.ResultErrorCode;
import net.siufung.core.result.ResultOk.ResultSuccessCode;
import net.siufung.core.utils.GsonUtil;
import net.siufung.core.utils.StringPool;

import java.time.LocalDateTime;
import java.util.Map;

/**
 * REST请求的返回模型，所有REST正常都返回该类的对象
 * @author 陈建峰
 * @since 2022/4/23 11:15 下午
 */
@Setter
@Getter
public class Result<T> implements GsonUtil.Gsonable {

    private static final long serialVersionUID = -6521895400027019084L;

    /**
     * 处理结果
     */
    private boolean success;
    /**
     * 处理结果数据信息
     */
    private T data;
    /**
     * 返回非主数据
     */
    private Map<String, Object> variables;
    /**
     * 处理结果描述信息
     */
    private String message;
    /**
     * 处理结果编码
     */
    private Integer code;
    /**
     * 处理结果请求得URL
     */
    private String url;
    /**
     * 返回错误信息堆栈
     */
    private String errorStackTrack;
    /**
     * 请求结果生成的时间戳
     */
    private String time;

    /**
     * 构造函数
     */
    public Result() {
        this.time = LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.NORM_DATETIME_FORMATTER);
    }

    /**
     * 构造函数
     * @param success 处理结果
     * @param data 处理结果数据信息
     * @param variables 返回非主数据
     * @param message 处理结果描述信息
     * @param code 处理结果编码
     * @param url 请求路径
     * @param errorStackTrack 返回错误信息堆栈
     */
    public Result(boolean success, T data, Map<String, Object> variables, String message, Integer code, String url, String errorStackTrack) {
        this.success = success;
        this.data = data;
        this.variables = variables;
        this.message = message;
        this.code = code;
        this.url = url;
        this.errorStackTrack = errorStackTrack;
        this.time = LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.NORM_DATETIME_FORMATTER);
    }

    /**
     * 构造函数
     * @param success 处理结果
     * @param data 处理结果数据信息
     * @param variables 返回非主数据
     * @param message 处理结果描述信息
     * @param code 处理结果编码
     * @param url 请求路径
     * @param errorStackTrack 返回错误信息堆栈
     * @return <T>
     */
    public static <T> Result<T> of(boolean success, T data, Map<String, Object> variables, String message, Integer code, String url, String errorStackTrack) {
        return new Result<T>(success, data, variables, message, code, url, errorStackTrack);
    }

    /**
     * 构造函数
     * @param success 处理结果
     * @param data 处理结果数据信息
     * @param variables 返回非主数据
     * @param message 处理结果描述信息
     * @param code 处理结果编码
     * @param url 请求路径
     * @return <T>
     */
    public static <T> Result<T> of(boolean success, T data, Map<String, Object> variables, String message, Integer code, String url) {
        return new Result<T>(success, data, variables, message, code, url, StringPool.EMPTY);
    }

    /**
     * 构造函数
     * @param success 处理结果
     * @param data 处理结果数据信息
     * @param variables 返回非主数据
     * @param message 处理结果描述信息
     * @param code 处理结果编码
     * @return <T>
     */
    public static <T> Result<T> of(boolean success, T data, Map<String, Object> variables, String message, Integer code) {
        return new Result<T>(success, data, variables, message, code, StringPool.EMPTY, StringPool.EMPTY);
    }

    /**
     * 构造函数
     * @param success 处理结果
     * @param data 处理结果数据信息
     * @param message 处理结果描述信息
     * @param code 处理结果编码
     * @return <T>
     */
    public static <T> Result<T> of(boolean success, T data,  String message, Integer code) {
        return new Result<T>(success, data, Maps.newHashMap(), message, code, StringPool.EMPTY, StringPool.EMPTY);
    }

    /**
     * 构造函数
     * @param success 处理结果
     * @param data 处理结果数据信息
     * @param variables 返回非主数据
     * @param resultType 结果类型
     * @param url 请求路径
     * @return <T>
     */
    public static <T> Result<T> of(boolean success, T data, Map<String, Object> variables, IResultType resultType, String url) {
        return new Result<T>(success, data, variables, resultType.getMessage(), resultType.getCode(), url, StringPool.EMPTY);
    }

    /**
     * 构造函数
     * @param success 处理结果
     * @param data 处理结果数据信息
     * @param variables 返回非主数据
     * @param resultType 结果类型
     * @return <T>
     */
    public static <T> Result<T> of(boolean success, T data, Map<String, Object> variables, IResultType resultType) {
        return new Result<T>(success, data, variables, resultType.getMessage(), resultType.getCode(), StringPool.EMPTY, StringPool.EMPTY);
    }


    /**
     * 构造函数
     * @param success 处理结果
     * @param data 处理结果数据信息
     * @param resultType 结果类型
     * @return <T>
     */
    public static <T> Result<T> of(boolean success, T data, IResultType resultType) {
        return new Result<T>(success, data, Maps.newHashMap(), resultType.getMessage(), resultType.getCode(), StringPool.EMPTY, StringPool.EMPTY);
    }

    /**
     * 构造函数
     * @param success 处理结果
     * @param resultType 结果类型
     * @return <T>
     */
    public static <T> Result<T> of(boolean success, IResultType resultType) {
        return new Result<T>(success, null, Maps.newHashMap(), resultType.getMessage(), resultType.getCode(), StringPool.EMPTY, StringPool.EMPTY);
    }

    /**
     * 请求成功返回信息
     * @param data 处理结果数据信息
     * @param message 处理结果描述信息
     * @param code 处理结果编码
     * @return <T>
     */
    public static <T> Result<T> ok(T data, String message, Integer code) {
        return Result.of(true, data, message, code);
    }

    /**
     * 请求成功返回信息
     * @param message 处理结果描述信息
     * @param code 处理结果编码
     * @return <T>
     */
    public static <T> Result<T> ok(String message, Integer code) {
        return Result.of(true, null, message, code);
    }

    /**
     * 请求成功返回信息
     * @param data 处理结果数据信息
     * @param resultType 结果类型
     * @return <T>
     */
    public static <T> Result<T> ok(T data, IResultType resultType) {
        return Result.of(true, data, resultType);
    }

    /**
     * 请求成功添加返回信息
     * @param data 处理结果数据信息
     * @param message 处理结果描述信息
     * @return <T>
     */
    public static <T> Result<T> ok(T data, String message) {
        return Result.of(true, data, message, ResultSuccessCode.DEFAULT_OK_CODE);
    }

    /**
     * 请求成功返回信息
     * @param resultType 结果类型
     * @return <T>
     */
    public static <T> Result<T> ok(IResultType resultType) {
        return Result.of(true, null, resultType);
    }

    /**
     * 请求成功返回信息
     * @param data 处理结果数据信息
     * @return <T>
     */
    public static <T> Result<T> ok(T data) {
        return Result.of(true, data, ResultOk.SUCCESS);
    }

    /**
     * 请求成功返回信息
     * @param message 处理结果描述信息
     * @return <T>
     */
    public static <T> Result<T> ok(String message) {
        return Result.of(true, null, message, ResultSuccessCode.DEFAULT_OK_CODE);
    }

    /**
     * 请求成功默认返回信息
     * @return <T>
     */
    public static <T> Result<T> ok() {
        return Result.ok(ResultOk.SUCCESS);
    }

    /**
     * 请求失败返回信息
     * @param data 处理结果数据信息
     * @param message 处理结果描述信息
     * @param code 处理结果编码
     * @return <T>
     */
    public static <T> Result<T> fail(T data, String message, Integer code) {
        return Result.of(false, data, message, code);
    }

    /**
     * 请求失败返回信息
     * @param message 处理结果描述信息
     * @param code 处理结果编码
     * @return <T>
     */
    public static <T> Result<T> fail(String message, Integer code) {
        return Result.of(false, null, message, code);
    }

    /**
     * 请求失败返回信息
     * @param data 处理结果数据信息
     * @param resultType 结果类型
     * @return <T>
     */
    public static <T> Result<T> fail(T data, IResultType resultType) {
        return Result.of(false, data, resultType);
    }

    /**
     * 请求失败添加返回信息
     * @param data 处理结果数据信息
     * @param message 处理结果描述信息
     * @return <T>
     */
    public static <T> Result<T> fail(T data, String message) {
        return Result.of(false, data, message, ResultSuccessCode.DEFAULT_OK_CODE);
    }

    /**
     * 请求失败返回信息
     * @param resultType 结果类型
     * @return <T>
     */
    public static <T> Result<T> fail(IResultType resultType) {
        return Result.of(false, null, resultType);
    }

    /**
     * 请求失败返回信息
     * @param data 处理结果数据信息
     * @return <T>
     */
    public static <T> Result<T> fail(T data) {
        return Result.of(false, data, ResultFail.ERROR);
    }

    /**
     * 请求失败返回信息
     * @param message 处理结果描述信息
     * @return <T>
     */
    public static <T> Result<T> fail(String message) {
        return Result.of(false, null, message, ResultErrorCode.DEFAULT_ERROR_CODE);
    }

    /**
     * 请求失败默认返回信息
     * @return <T>
     */
    public static <T> Result<T> fail() {
        return Result.fail(ResultFail.ERROR);
    }

}
